﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;

namespace MyFramework.Converters
{
    /// <summary>
    /// Enum to bool converter
    /// </summary>
    [ValueConversion(typeof(object), typeof(bool))]
    public class EnumToBoolConverter : IValueConverter
    {
        #region IValueConverter Members

        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        /// <exception cref="System.ArgumentException">This converter value must be an Enum</exception>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {

            Enum enumValue = value as Enum;
            if (enumValue == null)
            {
                throw new ArgumentException("This converter value must be an Enum");
            }

            if (Enum.IsDefined(enumValue.GetType(), parameter))
            {
                if (Enum.Parse(enumValue.GetType(), parameter.ToString()).Equals(value))
                {
                    return true;
                }

            }
            return false;
        }

        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value that is produced by the binding target.</param>
        /// <param name="targetType">The type to convert to.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {

            if (value == null || parameter == null)
            {
                return null;
            }

            targetType = GetNotNullableType(targetType);
            bool useValue = (bool)value;
            string targetValue = parameter.ToString();
            if (useValue)
            {
                return Enum.Parse(targetType, targetValue);
            }

            return null;

        }

        private bool IsNullableType(Type type)
        {
            return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
        }

        private Type GetNotNullableType(Type type)
        {
            if (!IsNullableType(type))
            {
                return type;
            }

            NullableConverter nc = new NullableConverter(type);
            return nc.UnderlyingType;
        }

        #endregion
    }
}
